/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
// Copyright tang.  All rights reserved.
// https://gitee.com/inrgihc/dbswitch
//
// Use of this source code is governed by a BSD-style license
//
// Author: tang (inrgihc@126.com)
// Date : 2020/1/2
// Location: beijing , china
/////////////////////////////////////////////////////////////
package com.je.meta.service.dbswitch.type;

import org.springframework.util.StringUtils;

import java.util.Arrays;

public enum SupportDbTypeEnum {

    MYSQL(1, "mysql", "com.mysql.jdbc.Driver", 3306,
            "/* ping */ SELECT 1",
            "jdbc:mysql://",
            new String[]{"jdbc:mysql://{host}[:{port}]/[{database}][\\?{params}]"}),
    MARIADB(2, "mariadb", "org.mariadb.jdbc.Driver", 3306,
            "SELECT 1",
            "jdbc:mariadb://",
            new String[]{"jdbc:mariadb://{host}[:{port}]/[{database}][\\?{params}]"}),
    ORACLE(3, "oracle", "oracle.jdbc.driver.OracleDriver", 1521,
            "SELECT 'Hello' from DUAL",
            "jdbc:oracle:thin:@",
            new String[]{"jdbc:oracle:thin:@{host}:{port}:{database}",
                    "jdbc:oracle:thin:@//{host}[:{port}]/{database}"}),
    SQLSERVER(4, "sqlserver", "com.microsoft.sqlserver.jdbc.SQLServerDriver", 1433,
            "SELECT 1+2 as a",
            "jdbc:sqlserver://",
            new String[]{"jdbc:sqlserver://{host}[:{port}][;DatabaseName={database}][;{params}]"}),
    POSTGRESQL(5, "postgresql", "org.postgresql.Driver", 5432,
            "SELECT 1",
            "jdbc:postgresql://",
            new String[]{"jdbc:postgresql://{host}[:{port}]/[{database}][\\?{params}]"}),
    DB2(6, "db2", "com.ibm.db2.jcc.DB2Driver", 50000,
            "SELECT 1 FROM SYSIBM.SYSDUMMY1",
            "jdbc:db2://",
            new String[]{"jdbc:db2://{host}:{port}/{database}[:{params}]"}),
    DM(7, "dm", "dm.jdbc.driver.DmDriver", 5236,
            "SELECT 'Hello' from DUAL",
            "jdbc:dm://",
            new String[]{"jdbc:dm://{host}:{port}[/{database}][\\?{params}]"}),
    KINGBASE(8, "kingbase", "com.kingbase8.Driver", 54321,
            "SELECT 1",
            "jdbc:kingbase8://",
            new String[]{"jdbc:kingbase8://{host}[:{port}]/[{database}][\\?{params}]"}),
    OSCAR(9, "oscar", "com.oscar.Driver", 2003,
            "SELECT 1",
            "jdbc:oscar://",
            new String[]{"jdbc:oscar://{host}[:{port}]/[{database}][\\?{params}]"}),
    GBASE8A(10, "gbase8a", "com.gbase.jdbc.Driver", 5258,
            "/* ping */ SELECT 1",
            "jdbc:gbase://",
            new String[]{"jdbc:gbase://{host}[:{port}]/[{database}][\\?{params}]"}),
    SYBASE(11, "sybase", "com.sybase.jdbc4.jdbc.SybDriver", 5000,
            "SELECT 1+2 as a",
            "jdbc:sybase:Tds:",
            new String[]{"jdbc:sybase:Tds:{host}[:{port}][/{database}][\\?{params}]"}),
    HIVE(12, "hive", "org.apache.hive.jdbc.HiveDriver", 10000,
            "SELECT 1",
            "jdbc:hive2://",
            new String[]{"jdbc:hive2://{host}[:{port}]/[{database}][\\?{params}]"}),
    // 参考文章：https://blog.csdn.net/wank1259162/article/details/104946744
    SQLITE3(13, "sqlite3", "org.sqlite.JDBC", 0,
            "SELECT 1",
            "jdbc:sqlite:",
            new String[]{"jdbc:sqlite:{file}", "jdbc:sqlite::resource:{file}"}),
    ;

    private int id;
    private String name;
    private String driver;
    private int port;
    private String sql;
    private String urlPrefix;
    private String[] url;

    SupportDbTypeEnum(int id, String name, String driver, int port, String sql, String urlPrefix, String[] url) {
        this.id = id;
        this.name = name;
        this.driver = driver;
        this.port = port;
        this.sql = sql;
        this.urlPrefix = urlPrefix;
        this.url = url;
    }

    public static SupportDbTypeEnum getSupportDbTypeEnumByName(String dbType) {
        if (MYSQL.getName().equals(dbType)) {
            return MYSQL;
        }
        if (MARIADB.getName().equals(dbType)) {
            return MARIADB;
        }
        if (ORACLE.getName().equals(dbType)) {
            return ORACLE;
        }
        if (SQLSERVER.getName().equals(dbType)) {
            return SQLSERVER;
        }
        if (POSTGRESQL.getName().equals(dbType)) {
            return POSTGRESQL;
        }
        if (DB2.getName().equals(dbType)) {
            return DB2;
        }
        if (DM.getName().equals(dbType)) {
            return DM;
        }
        if (KINGBASE.getName().equals(dbType)) {
            return KINGBASE;
        }
        if (OSCAR.getName().equals(dbType)) {
            return OSCAR;
        }
        if (GBASE8A.getName().equals(dbType)) {
            return GBASE8A;
        }
        if (SYBASE.getName().equals(dbType)) {
            return SYBASE;
        }
        if (HIVE.getName().equals(dbType)) {
            return HIVE;
        }
        if (SQLITE3.getName().equals(dbType)) {
            return SQLITE3;
        }
        return null;
    }

    public boolean hasDatabaseName() {
        return !Arrays.asList(DM, SQLITE3).contains(this);
    }

    public boolean hasFilePath() {
        return this == SQLITE3;
    }

    public boolean hasAddress() {
        return this != SQLITE3;
    }

    public static SupportDbTypeEnum of(String name) {
        if (!StringUtils.isEmpty(name)) {
            for (SupportDbTypeEnum type : SupportDbTypeEnum.values()) {
                if (type.getName().equalsIgnoreCase(name)) {
                    return type;
                }
            }
        }

        throw new IllegalArgumentException("cannot find enum name: " + name);
    }

    public static boolean isUnsupportedTargetSqlite(String url) {
        String prefix1 = "jdbc:sqlite::resource:";
        //String prefix2 = "jdbc:sqlite::memory:";
        return url.startsWith(prefix1);
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public String getSql() {
        return sql;
    }

    public void setSql(String sql) {
        this.sql = sql;
    }

    public String getUrlPrefix() {
        return urlPrefix;
    }

    public void setUrlPrefix(String urlPrefix) {
        this.urlPrefix = urlPrefix;
    }

    public String[] getUrl() {
        return url;
    }

    public void setUrl(String[] url) {
        this.url = url;
    }
}
